
package com.qing.utils.lottery.ssq.analyse;

import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONUtil;
import com.qing.utils.lottery.ssq.bean.SsqGroupedTypeResult;
import com.qing.utils.lottery.ssq.bean.SsqResponse;
import com.qing.utils.lottery.ssq.bean.SsqResponseResult;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collector;
import java.util.stream.Collectors;

public class FiveSectionAnalyser extends Analyser {

    public static final int RED_BIG_BEGIN = 28;
    public static final int RED_BIG_END = 33;

    private static final int RED_MIDDLE_BIG_BEGIN = 22;
    private static final int RED_MIDDLE_BIG_END = 27;

    private static final int RED_MIDDLE_BEGIN = 15;
    private static final int RED_MIDDLE_END = 21;

    private static final int RED_MIDDLE_SMALL_BEGIN = 8;
    private static final int RED_MIDDLE_SMALL_END = 14;
    private static final int RED_SMALL_BEGIN = 1;
    private static final int RED_SMALL_END = 7;

    private static final int[] RED_BIG_SECTION = new int[RED_BIG_END - RED_BIG_BEGIN + 1];
    private static final int[] RED_MIDDLE_BIG_SECTION = new int[RED_MIDDLE_BIG_END - RED_MIDDLE_BIG_BEGIN + 1];
    private static final int[] RED_MIDDLE_SECTION = new int[RED_MIDDLE_END - RED_MIDDLE_BEGIN + 1];
    private static final int[] RED_MIDDLE_SMALL_SECTION = new int[RED_MIDDLE_SMALL_END - RED_MIDDLE_SMALL_BEGIN + 1];
    private static final int[] RED_SMALL_SECTION = new int[RED_SMALL_END - RED_SMALL_BEGIN + 1];



    private static final int BLUE_SMALL_BEGIN = 1;
    private static final int BLUE_SMALL_END = 4;
    public static final int BLUE_MIDDLE_SMALL_BEGIN = 5;
    public static final int BLUE_MIDDLE_SMALL_END = 7;
    public static final int BLUE_MIDDLE_BEGIN = 8;
    public static final int BLUE_MIDDLE_END = 10;
    public static final int BLUE_MIDDLE_BIG_BEGIN = 11;
    public static final int BLUE_MIDDLE_BIG_END = 13;
    public static final int BLUE_BIG_BEGIN = 14;
    public static final int BLUE_BIG_END = 16;
    private static final int[] BLUE_BIG_SECTION = new int[BLUE_BIG_END - BLUE_BIG_BEGIN + 1];
    private static final int[] BLUE_MIDDLE_BIG_SECTION = new int[BLUE_MIDDLE_BIG_END - BLUE_MIDDLE_BIG_BEGIN + 1];
    private static final int[] BLUE_MIDDLE_SECTION = new int[BLUE_MIDDLE_END - BLUE_MIDDLE_BEGIN + 1];
    private static final int[] BLUE_MIDDLE_SMALL_SECTION = new int[BLUE_MIDDLE_SMALL_END - BLUE_MIDDLE_SMALL_BEGIN + 1];
    private static final int[] BLUE_SMALL_SECTION = new int[BLUE_SMALL_END - BLUE_SMALL_BEGIN + 1];


    static {
        initRedSections();
        initBlueSection();
    }

    private static void initBlueSection() {
        for (int i = BLUE_SMALL_BEGIN; i <= BLUE_SMALL_BEGIN; i++) {
            BLUE_SMALL_SECTION[i - 1] = i;
        }

        for (int i = BLUE_MIDDLE_SMALL_BEGIN; i <= BLUE_MIDDLE_SMALL_END; i++) {
            BLUE_MIDDLE_SMALL_SECTION[i - BLUE_MIDDLE_SMALL_BEGIN] = i;

        }

        for (int i = BLUE_MIDDLE_BEGIN; i <= BLUE_MIDDLE_END; i++) {
            BLUE_MIDDLE_SECTION[i - BLUE_MIDDLE_BEGIN] = i;

        }

        for (int i = BLUE_MIDDLE_BIG_BEGIN; i <= BLUE_MIDDLE_BIG_END; i++) {
            BLUE_MIDDLE_BIG_SECTION[i - BLUE_MIDDLE_BIG_BEGIN] = i;

        }

        for (int i = BLUE_BIG_BEGIN; i <= BLUE_BIG_END; i++) {
            BLUE_BIG_SECTION[i - BLUE_BIG_BEGIN] = i;

        }
    }

    private static void initRedSections() {
        for (int i = RED_SMALL_BEGIN; i <= RED_SMALL_END; i++) {
            RED_SMALL_SECTION[i - 1] = i;
        }


        for (int i = RED_MIDDLE_SMALL_BEGIN; i <= RED_MIDDLE_SMALL_END; i++) {
            RED_MIDDLE_SMALL_SECTION[i - RED_MIDDLE_SMALL_BEGIN] = i;

        }


        for (int i = RED_MIDDLE_BEGIN; i <= RED_MIDDLE_END; i++) {
            RED_MIDDLE_SECTION[i - RED_MIDDLE_BEGIN] = i;

        }

        for (int i = RED_MIDDLE_BIG_BEGIN; i <= RED_MIDDLE_BIG_END; i++) {
            RED_MIDDLE_BIG_SECTION[i - RED_MIDDLE_BIG_BEGIN] = i;

        }
        for (int i = RED_BIG_BEGIN; i <= RED_BIG_END; i++) {
            RED_BIG_SECTION[i - RED_BIG_BEGIN] = i;

        }
    }

    public static void main(String[] args) {
        FiveSectionAnalyser twoSectionAnalyser = new FiveSectionAnalyser();
        List<SsqResponseResult> paredList = twoSectionAnalyser.parse("D:\\Workspaces\\MySpace\\IDEA\\common-utils\\lottery-utils\\src\\main\\resources\\ssqResponse\\ssqResponse_2023-11-19_10_48_09");

        Collector<AnalyserParam, ?, List<AnalyserParam>> collector = Collectors.toList();
        List<AnalyserParam> paramList = paredList.stream().map(r -> {
            String red = r.getRed();
            String blue = r.getBlue();
            String[] split = red.split(",");
            int[] reds = new int[split.length];
            for (int i = 0; i < split.length; i++) {
                String s = split[i];
                reds[i] = Integer.parseInt(s.trim());
            }
            int[] blues = new int[1];
            blues[0] = Integer.parseInt(blue.trim());
            return new AnalyserParam(reds, blues, red, blue);
        }).collect(collector).stream().collect(collector);
        List<AnalyserResult> analyserResultList = twoSectionAnalyser.analyseList(paramList);
        calculateRed(twoSectionAnalyser, analyserResultList);
        calculateBlue(twoSectionAnalyser, analyserResultList);


    }

    private static void calculateRed(FiveSectionAnalyser twoSectionAnalyser, List<AnalyserResult> analyserResultList) {
        Map<String, SsqGroupedTypeResult> resultMap = twoSectionAnalyser.groupRedResult(analyserResultList);
        System.out.println("======================红球开奖分析 开始=====================");
        Collection<SsqGroupedTypeResult> values = resultMap.values();
        for (SsqGroupedTypeResult entry : values) {
            System.out.println("*****红球开出类型: "+entry.getTypeKey()+", 下一期开出类型:  ");
            for (Map.Entry<String, Integer> nextEntry : entry.getNextTypeCountMap().entrySet()) {
                System.out.println("------------------" + nextEntry.getKey() + ":  " + nextEntry.getValue());
            }
        }

        SsqGroupedTypeResult typeResult = resultMap.get(analyserResultList.get(0).getRedTypeKey());
        System.out.println("红球最新一期开出的类型: " + typeResult.getTypeKey() + ", 下一期开出过的类型有:  ");
        Map<String, Integer> nextTypeCountMap = typeResult.getNextTypeCountMap();
        for (Map.Entry<String, Integer> nextEntry : nextTypeCountMap.entrySet()) {
            System.out.println("------------------" + nextEntry.getKey() + ":  " + nextEntry.getValue());
        }

        System.out.println("======================红球开奖分析 结束=====================");
    }


    private static void calculateBlue(FiveSectionAnalyser twoSectionAnalyser, List<AnalyserResult> analyserResultList) {
        Map<String, SsqGroupedTypeResult> resultMap = twoSectionAnalyser.groupBlueResult(analyserResultList);
        System.out.println("======================蓝球开奖分析 开始=====================");
        Collection<SsqGroupedTypeResult> values = resultMap.values();
        for (SsqGroupedTypeResult entry : values) {
            System.out.println("*****蓝球开出类型: "+entry.getTypeKey()+", 下一期开出类型:  ");
            for (Map.Entry<String, Integer> nextEntry : entry.getNextTypeCountMap().entrySet()) {
                System.out.println("------------------" + nextEntry.getKey() + ":  " + nextEntry.getValue());
            }
        }

        SsqGroupedTypeResult typeResult = resultMap.get(analyserResultList.get(0).getBlueTypeKey());
        System.out.println("蓝球最新一期开出的类型: " + typeResult.getTypeKey() + ", 下一期开出过的类型有:  ");
        Map<String, Integer> nextTypeCountMap = typeResult.getNextTypeCountMap();
        for (Map.Entry<String, Integer> nextEntry : nextTypeCountMap.entrySet()) {
            System.out.println("------------------" + nextEntry.getKey() + ":  " + nextEntry.getValue());
        }
        System.out.println("======================蓝球开奖分析 结束=====================");
    }

    public List<SsqResponseResult> parse(String filePath) {
        String s = FileUtil.readUtf8String(filePath);
        SsqResponse bean = JSONUtil.toBean(s, SsqResponse.class);
        return bean.getResult();
    }

    public Map<String, SsqGroupedTypeResult> groupRedResult(List<AnalyserResult> resultList) {
        Map<String, SsqGroupedTypeResult> resultMap = new HashMap<>(8, 1);
        Map<String, List<AnalyserResult>> redMap = new HashMap<>(8, 1);
        for (AnalyserResult result : resultList) {
            String key = result.getRedTypeKey();
            List<AnalyserResult> typeResultList = redMap.computeIfAbsent(key, k -> new ArrayList<>());
            typeResultList.add(result);
        }

        for (int i = resultList.size() - 1; i >= 1; i--) {

            AnalyserResult currentResult = resultList.get(i);

            // 当前key的result
            String currentTypeKey = currentResult.getRedTypeKey();
            SsqGroupedTypeResult typeResult = resultMap.computeIfAbsent(currentTypeKey, k -> {
                SsqGroupedTypeResult typeResult1 = new SsqGroupedTypeResult();
                typeResult1.setTypeKey(k);
                typeResult1.setAnalyserResultList(redMap.get(k));
                typeResult1.setNextTypeCountMap(new HashMap<>(8, 1));
                return typeResult1;
            });

            // 下一次出现的数量+1
            AnalyserResult nextResult = resultList.get(i - 1);
            String nextTypeKey = nextResult.getRedTypeKey();
            Map<String, Integer> nextTypeCountMap = typeResult.getNextTypeCountMap();
            Integer count = nextTypeCountMap.computeIfAbsent(nextTypeKey, k -> 0);
            nextTypeCountMap.put(nextTypeKey, ++count);

        }
        return resultMap;
    }


    public Map<String, SsqGroupedTypeResult> groupBlueResult(List<AnalyserResult> resultList) {
        Map<String, SsqGroupedTypeResult> resultMap = new HashMap<>(8, 1);
        Map<String, List<AnalyserResult>> redMap = new HashMap<>(8, 1);
        for (AnalyserResult result : resultList) {
            String key = result.getBlueTypeKey();
            List<AnalyserResult> typeResultList = redMap.computeIfAbsent(key, k -> new ArrayList<>());
            typeResultList.add(result);
        }

        for (int i = resultList.size() - 1; i >= 1; i--) {

            AnalyserResult currentResult = resultList.get(i);

            // 当前key的result
            String currentTypeKey = currentResult.getBlueTypeKey();
            SsqGroupedTypeResult typeResult = resultMap.computeIfAbsent(currentTypeKey, k -> {
                SsqGroupedTypeResult typeResult1 = new SsqGroupedTypeResult();
                typeResult1.setTypeKey(k);
                typeResult1.setAnalyserResultList(redMap.get(k));
                typeResult1.setNextTypeCountMap(new HashMap<>(8, 1));
                return typeResult1;
            });

            // 下一次出现的数量+1
            AnalyserResult nextResult = resultList.get(i - 1);
            String nextTypeKey = nextResult.getBlueTypeKey();
            Map<String, Integer> nextTypeCountMap = typeResult.getNextTypeCountMap();
            Integer count = nextTypeCountMap.computeIfAbsent(nextTypeKey, k -> 0);
            nextTypeCountMap.put(nextTypeKey, ++count);

        }
        return resultMap;
    }


    public List<AnalyserResult> analyseList(List<AnalyserParam> params) {
        return params.stream().map(this::analyse).collect(Collectors.toList());
    }


    public AnalyserResult analyse(AnalyserParam param) {
        AnalyserResult result = new AnalyserResult();
        result.setRedSectionList(analyseRed(param.getRedValues()));
        result.setBlueSectionList(analyseBlue(param.getBlueValues()));

        return result;
    }

    @Override
    protected List<AnalyserResult.ResultSection> analyseRed(int[] redValues) {
        int redSmallCount = 0;
        int redMiddleCount = 0;
        int redBigCount = 0;
        int redMiddleSmallCount = 0;
        int redMiddleBigCount = 0;
        for (int redValue : redValues) {
            if (analyseRedSmall(redValue)) {
                redSmallCount++;
            } else if (analyseRedMiddle(redValue)) {
                redMiddleCount++;
            } else if (analyseRedMiddleSmall(redValue)) {
                redMiddleSmallCount++;
            } else if (analyseRedMiddleBig(redValue)) {
                redMiddleBigCount++;
            } else {
                redBigCount++;
            }
        }

        AnalyserResult.ResultSection smallSection = new AnalyserResult.ResultSection(FiveSectionAnalyser.RED_SMALL_SECTION, redSmallCount, AnalyserResult.SectionType.LOW);
        AnalyserResult.ResultSection middleSection = new AnalyserResult.ResultSection(FiveSectionAnalyser.RED_MIDDLE_SECTION, redMiddleCount, AnalyserResult.SectionType.MIDDLE);
        AnalyserResult.ResultSection middleSmallSection = new AnalyserResult.ResultSection(FiveSectionAnalyser.RED_MIDDLE_SMALL_SECTION, redMiddleSmallCount, AnalyserResult.SectionType.MIDDLE_LOW);
        AnalyserResult.ResultSection middleBigSection = new AnalyserResult.ResultSection(FiveSectionAnalyser.RED_MIDDLE_BIG_SECTION, redMiddleBigCount, AnalyserResult.SectionType.MIDDLE_HIGH);
        AnalyserResult.ResultSection bigSection = new AnalyserResult.ResultSection(FiveSectionAnalyser.RED_BIG_SECTION, redBigCount, AnalyserResult.SectionType.HIGH);
        return Arrays.asList(smallSection, middleSmallSection, middleSection, middleBigSection, bigSection);
    }


    private boolean analyseRedSmall(int redValue) {

        for (int i : RED_SMALL_SECTION) {
            if (i == redValue) {
                return true;
            }
        }
        return false;
    }

    private boolean analyseRedMiddle(int redValue) {
        for (int i : RED_MIDDLE_SECTION) {
            if (i == redValue) {
                return true;
            }
        }
        return false;
    }

    private boolean analyseRedMiddleSmall(int redValue) {

        for (int i : RED_MIDDLE_SMALL_SECTION) {
            if (i == redValue) {
                return true;
            }
        }
        return false;
    }

    private boolean analyseRedMiddleBig(int redValue) {
        for (int i : RED_MIDDLE_BIG_SECTION) {
            if (i == redValue) {
                return true;
            }
        }
        return false;
    }


    @Override
    protected List<AnalyserResult.ResultSection> analyseBlue(int[] blueValues) {
        int blueSmallCount = 0;
        int blueMiddleCount = 0;
        int blueBigCount = 0;
        int blueMiddleSmallCount = 0;
        int blueMiddleBigCount = 0;
        for (int blueValue : blueValues) {
            if (analyseBlueSmall(blueValue)) {
                blueSmallCount++;
            } else if (analyseBlueMiddle(blueValue)) {
                blueMiddleCount++;
            } else if (analyseBlueMiddleSmall(blueValue)) {
                blueMiddleSmallCount++;
            } else if (analyseBlueMiddleBig(blueValue)) {
                blueMiddleBigCount++;
            } else {
                blueBigCount++;
            }
        }

        AnalyserResult.ResultSection smallSection = new AnalyserResult.ResultSection(FiveSectionAnalyser.BLUE_SMALL_SECTION, blueSmallCount, AnalyserResult.SectionType.LOW);
        AnalyserResult.ResultSection middleSection = new AnalyserResult.ResultSection(FiveSectionAnalyser.BLUE_MIDDLE_SECTION, blueMiddleCount, AnalyserResult.SectionType.MIDDLE);
        AnalyserResult.ResultSection middleSmallSection = new AnalyserResult.ResultSection(FiveSectionAnalyser.BLUE_MIDDLE_SMALL_SECTION, blueMiddleSmallCount, AnalyserResult.SectionType.MIDDLE_LOW);
        AnalyserResult.ResultSection middleBigSection = new AnalyserResult.ResultSection(FiveSectionAnalyser.BLUE_MIDDLE_BIG_SECTION, blueMiddleBigCount, AnalyserResult.SectionType.MIDDLE_HIGH);
        AnalyserResult.ResultSection bigSection = new AnalyserResult.ResultSection(FiveSectionAnalyser.BLUE_BIG_SECTION, blueBigCount, AnalyserResult.SectionType.HIGH);
        return Arrays.asList(smallSection, middleSmallSection, middleSection, middleBigSection, bigSection);
    }


    private boolean analyseBlueSmall(int blueValue) {
        for (int i : BLUE_SMALL_SECTION) {
            if (i == blueValue) {
                return true;
            }
        }
        return false;

    }

    private boolean analyseBlueMiddle(int blueValue) {
        for (int i : BLUE_MIDDLE_SECTION) {
            if (i == blueValue) {
                return true;
            }
        }
        return false;
    }


    private boolean analyseBlueMiddleSmall(int blueValue) {
        for (int i : BLUE_MIDDLE_SMALL_SECTION) {
            if (i == blueValue) {
                return true;
            }
        }
        return false;

    }

    private boolean analyseBlueMiddleBig(int blueValue) {
        for (int i : BLUE_MIDDLE_BIG_SECTION) {
            if (i == blueValue) {
                return true;
            }
        }
        return false;
    }


}
